package com.ruoyi.common.utils.file;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.ruoyi.common.config.OssConfig;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;

/**
 * 阿里云OSS工具类
 */
@Component
public class OssUtil {

    @Autowired
    private OssConfig ossConfig;

    /**
     * 上传文件
     *
     * @param file 文件对象
     * @param dir  存储目录
     * @return 文件访问路径
     * @throws IOException
     */
    public String uploadFile(MultipartFile file, String dir) throws IOException {
        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
        try {
            // 获取文件名
            String originalFilename = file.getOriginalFilename();
            // 获取文件后缀
            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 生成文件名
            String fileName = UUID.randomUUID().toString() + suffix;
            // 如果指定了目录，则使用指定的目录
            String objectName;
            if (StringUtils.isNotEmpty(dir)) {
                objectName = dir + "/" + fileName;
            } else if (StringUtils.isNotEmpty(ossConfig.getDir())) {
                // 否则使用配置的目录
                objectName = ossConfig.getDir() + "/" + fileName;
            } else {
                objectName = fileName;
            }

            // 创建上传Object的Metadata
            ObjectMetadata metadata = new ObjectMetadata();
            // 设置ContentLength
            metadata.setContentLength(file.getSize());
            // 设置Content-Type
            metadata.setContentType(getContentType(suffix));

            // 上传文件
            PutObjectRequest putObjectRequest = new PutObjectRequest(ossConfig.getBucketName(), objectName, file.getInputStream(), metadata);
            ossClient.putObject(putObjectRequest);

            // 设置URL过期时间
            Date expiration = new Date(System.currentTimeMillis() + (ossConfig.getExpireDays() != null ? ossConfig.getExpireDays() : 1) * 24 * 3600 * 1000);
            // 生成URL
            URL url = ossClient.generatePresignedUrl(ossConfig.getBucketName(), objectName, expiration);
            return url.toString();
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
    }

    /**
     * 删除文件
     *
     * @param fileName 文件名（包含路径）
     */
    public void deleteFile(String fileName) {
        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
        try {
            // 删除文件
            ossClient.deleteObject(ossConfig.getBucketName(), fileName);
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
    }

    /**
     * 获取文件
     *
     * @param fileName 文件名（包含路径）
     * @return 文件流
     */
    public InputStream getFile(String fileName) {
        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
        try {
            // 获取文件
            OSSObject ossObject = ossClient.getObject(ossConfig.getBucketName(), fileName);
            return ossObject.getObjectContent();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取文件访问URL
     *
     * @param fileName 文件名（包含路径）
     * @return 文件访问URL
     */
    public String getFileUrl(String fileName) {
        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
        try {
            // 设置URL过期时间
            Date expiration = new Date(System.currentTimeMillis() + (ossConfig.getExpireDays() != null ? ossConfig.getExpireDays() : 1) * 24 * 3600 * 1000);
            // 生成URL
            URL url = ossClient.generatePresignedUrl(ossConfig.getBucketName(), fileName, expiration);
            return url.toString();
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
    }

    /**
     * 根据文件后缀获取ContentType
     *
     * @param suffix 文件后缀
     * @return ContentType
     */
    private String getContentType(String suffix) {
        if (suffix.equalsIgnoreCase(".docx")) {
            return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        } else if (suffix.equalsIgnoreCase(".pdf")) {
            return "application/pdf";
        } else {
            return "application/octet-stream";
        }
    }

    /**
     * 下载文件
     *
     * @param fileUrl     文件URL或路径
     * @param outputStream 输出流
     * @throws IOException
     */
    public void downloadFile(String fileUrl, OutputStream outputStream) throws IOException {
        // 提取文件名
        String objectName = extractObjectNameFromUrl(fileUrl);
        if (StringUtils.isEmpty(objectName)) {
            throw new IOException("无效的文件URL: " + fileUrl);
        }

        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
        try {
            // 检查文件是否存在
            boolean exists = ossClient.doesObjectExist(ossConfig.getBucketName(), objectName);
            if (!exists) {
                throw new IOException("文件不存在: " + objectName);
            }

            // 获取文件
            OSSObject ossObject = ossClient.getObject(ossConfig.getBucketName(), objectName);
            // 将文件内容写入输出流
            IOUtils.copy(ossObject.getObjectContent(), outputStream);
            outputStream.flush();
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
    }

    /**
     * 获取文件预览URL
     *
     * @param fileUrl 文件URL或路径
     * @return 预览URL
     */
    public String getPreviewUrl(String fileUrl) {
        // 如果是完整URL，直接返回
        if (fileUrl.startsWith("http") && fileUrl.contains("?")) {
            return fileUrl;
        }

        // 提取文件名
        String objectName = extractObjectNameFromUrl(fileUrl);
        if (StringUtils.isEmpty(objectName)) {
            return fileUrl; // 如果无法提取文件名，直接返回原URL
        }

        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
        try {
            // 检查文件是否存在
            boolean exists = ossClient.doesObjectExist(ossConfig.getBucketName(), objectName);
            if (!exists) {
                return fileUrl; // 如果文件不存在，直接返回原URL
            }

            // 设置URL过期时间
            Date expiration = new Date(System.currentTimeMillis() + (ossConfig.getExpireDays() != null ? ossConfig.getExpireDays() : 1) * 24 * 3600 * 1000);
            // 生成URL
            URL url = ossClient.generatePresignedUrl(ossConfig.getBucketName(), objectName, expiration);
            return url.toString();
        } finally {
            // 关闭OSSClient
            ossClient.shutdown();
        }
    }

    /**
     * 从URL或路径提取文件名
     *
     * @param fileUrl 文件URL或路径
     * @return 文件名
     */
    private String extractObjectNameFromUrl(String fileUrl) {
        // 如果是完整URL，提取文件名
        if (fileUrl.startsWith("http")) {
            try {
                // 解析URL
                URL url = new URL(fileUrl);
                String path = url.getPath();

                // 如果路径以斜线开头，去除斜线
                if (path.startsWith("/")) {
                    path = path.substring(1);
                }

                // 提取文件名
                String host = url.getHost();
                if (host.contains(ossConfig.getBucketName() + ".")) {
                    // 如果URL包含bucket名，直接返回路径
                    return path;
                } else {
                    // 如果URL不包含bucket名，提取文件名
                    String fileName = path.substring(path.lastIndexOf("/") + 1);
                    // 如果文件名包含参数，去除参数
                    if (fileName.contains("?")) {
                        fileName = fileName.substring(0, fileName.indexOf("?"));
                    }

                    // 如果配置了目录，追加目录
                    if (StringUtils.isNotEmpty(ossConfig.getDir())) {
                        return ossConfig.getDir() + "/" + fileName;
                    } else {
                        return fileName;
                    }
                }
            } catch (Exception e) {
                // 如果解析URL失败，直接返回文件名
                String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
                if (fileName.contains("?")) {
                    fileName = fileName.substring(0, fileName.indexOf("?"));
                }

                // 如果配置了目录，追加目录
                if (StringUtils.isNotEmpty(ossConfig.getDir())) {
                    return ossConfig.getDir() + "/" + fileName;
                } else {
                    return fileName;
                }
            }
        } else {
            // 如果不是完整URL，直接返回文件名
            return fileUrl;
        }
    }
}
